<template>
    <div class="ele-upload-image">
<!--        :drag="Boolean(drag)"-->
        <el-upload
                   class="upload-demo"
                   :accept="accept"
                   :action="action"
                   :before-upload="handleBeforeUpload"
                   :data="data"
                   :disabled="uploading"
                   :headers="headers"
                   :http-request="httpRequest"
                   :limit="limit"
                   :list-type="drag ? 'picture' : 'picture-card'"
                   :multiple="multiple"
                   :name="name"
                   :on-change="handleChange"
                   :on-error="handleUploadError"
                   :on-exceed="handleExceed"
                   :on-success="handleUploadSuccess"
                   :show-file-list="false"
                   :withCredentials="withCredentials"
                   ref="upload"
                   v-show="isShowUpload">
            <div v-loading="uploading">
                <!-- drag显示 -->
                <template v-if="drag">
<!--                    <i class="el-icon-upload"></i>-->
<!--                    <div class="el-upload__text">-->
<!--                        将文件拖到此处，或-->
<!--                        <em>{{showText}}</em>-->
<!--                    </div>-->
                    <el-button type="primary" size="mini">{{showText}}</el-button>
                </template>

                <!-- 非drag -->
                <template v-else>
                    <div :style="{ width: size + 'px', height: size + 'px', lineHeight: size + 'px' }">
                        <el-button type="primary" size="small" v-if="size > 60">{{showText}}</el-button>
                        <i class="el-icon-plus" v-else></i>
                    </div>
                </template>
            </div>
            <!-- 公共 -->
            <div class="el-upload__tip" slot="tip" v-if="isShowTip" >
<!--                只能上传 <b style="color: #F56C6C">{{fileType ? fileType.join('/') : '图片'}}</b>-->
<!--                格式文件，且大小不超过<b style="color: #F56C6C">{{fileSize}}Mb</b>-->
<!--              建议尺寸：pc端 1920*667px；H5 750*918px-->
            </div>
        </el-upload>

      <!-- 图片列表 -->
      <div :key="index" class="el-upload-list__item"  v-for="(source, index) of computedSources" v-if="multiple">
        <img v-lazy="source.thumb" alt="" style="width: 120px;height: 120px;object-fit: cover" v-if="source.thumb" />
        <span @click="handleRemove(index)" class="remove-icon"><i class="iconfont iconicon_close"></i> </span>
      </div>

        <!-- 图片列表 -->
        <single-pic
                v-if="!multiple"
                :lazy="lazy"
                :remove-fn="handleRemove"
                :sliceSingle="true"
                :source="value"
                :thumbSuffix="thumbSuffix"
                :title="title"
                :width="size"
                :type="type"
                :isVideo="isVideo"
        />
    </div>
</template>

<script>
import singlePic from './single-pic';
export default {
    name: 'uploadFile',
    components: {
        singlePic
    },
    props: {
        showText: {
            type: String,
            default: '点击上传'
        },
        // 值
        value: {
            type: [String, Array],
            default () {
                return [];
            }
        },
        showFileList: {
            type: Boolean,
            default: false
        },
        // 是否剪裁
        crop: {
            type: Boolean,
            default: false
        },
        // 图片显示大小
        size: {
            type: Number,
            default: 150
        },
        // 裁剪高度
        cropHeight: {
            type: Number
        },
        // 裁剪宽度
        cropWidth: {
            type: Number
        },
        // 大小限制(MB), 默认5MB
        fileSize: {
            type: Number,
            default: 20
        },
        // 响应处理函数
        responseFn: Function,
        // 文件类型, 例如['png', 'jpg', 'jpeg']
        fileType: {
            type: Array,
            default: () => ['png', 'jpg', 'jpeg']
        },
        // 缩略图后缀, 例如七牛云缩略图样式 (?imageView2/1/w/20/h/20)
        thumbSuffix: {
            type: String,
            default: ''
        },
        // 是否显示提示
        isShowTip: {
            type: Boolean,
            default: true
        },
        // 弹窗标题
        title: String,
        // 图片懒加载
        lazy: {
            type: Boolean,
            default: false
        },
        // 上传地址 (同官网)
        action: {
            type: String,
            required: true
        },
        // 设置上传的请求头部(同官网)
        headers: Object,
        // 文件个数显示(同官网)
        limit: Number,
        // 是否启用拖拽上传 (同官网)
        drag: {
            type: Boolean,
            default: false
        },
        // 支持发送cookie凭证信息(同官网)
        withCredentials: {
            type: Boolean,
            default: false
        },
        // 是否支持多选文件 (同官网)
        multiple: {
            type: Boolean,
            default: false
        },
        // 上传时附带的额外参数(同官网)
        data: Object,
        // 上传的文件字段名 (同官网)
        name: {
            type: String,
            default: 'file'
        },
        // 覆盖默认的上传行为，可以自定义上传的实现 (同官网)
        httpRequest: Function,
        // 接受上传的文件类型（thumbnail-mode 模式下此参数无效）(同官网)
        accept: {
            type: String,
            default: 'image/jpeg,image/jpg,image/png'
        },
        type: {
            type: String,
            default: 'image',
            validator (value) {
                return ['image', 'file', 'image-auto'].includes(value);
            }
        },
        isVideo: {
            type: Boolean,
            default: false
        }
    },
    data () {
        return {
            cropData: {},
            isShowCrop: false,
            uploading: false,
            fileList: this.value || [],
            uploadType: ''
        };
    },
    computed: {
        computedSources () {
            const sources = this.value;
            if (typeof sources === 'string') {
                // 传入参数为 string
                return [this.getStringSource(sources)];
            } else if (sources instanceof Array) {
                // 传入参数为 array, 数据里面既可以有string 又可以有 object
                const res = [];
                sources.forEach((item) => {
                    if (item instanceof Object) {
                        res.push(this.getObjectSource(item));
                    } else if (typeof item === 'string') {
                        res.push(this.getStringSource(item));
                    } else {
                        console.warn('数组元素错误', sources, item);
                    }
                });
                return res;
            } else if (sources instanceof Object) {
                // 传入参数为 object
                return [this.getObjectSource(sources)];
            } else {
                return [];
            }
        },
        computedValues () {
            if (this.value) {
                if (typeof this.value === 'string') {
                    return [this.value];
                } else {
                    return [...this.value];
                }
            } else {
                return [];
            }
        },
        isShowUpload () {
            if (this.multiple) {
                return true;
            } else {
                return this.computedValues.length === 0;
            }
        },
        successFiles () {
            return this.fileList.filter((file) => file.status === 'success');
        },
        multipleVal () {
            let d = [];
            if (Array.isArray(this.value)) {
                this.value.map((val) => d.push({name: val, src: val}));
            }
            return d;
        }
    },
    watch: {
        isShowCrop (value) {
            if (value === false) {
                this.cropData = {};
            }
        }
    },
    methods: {
        // 获取字符串形式来源
        getStringSource (src) {
            let thumb = src;
            if (this.type === 'image' && this.thumbSuffix) {
                thumb += this.thumbSuffix;
            }
            return {
                type: this.type,
                src: src,
                thumb: thumb
            };
        },
        handleSetFileSet (fileName, fileType, fileSize) {
            const uid = this.cropData.uid || new Date().getTime();
            this.cropData = {
                name: fileName,
                percentage: 0,
                size: fileSize,
                type: fileType,
                status: 'ready',
                uid: uid
            };
        },
        handleCropSuccess (b64Data) {
            this.cropData.url = b64Data;
        },
        handleCropUploadError (status) {
            this.$message.error('上传失败, 请重试');
            this.$emit('error', status);
        },
        handleCropUploadSuccess (response) {
            this.cropData.status = 'success';
            this.cropData.percentage = 100;
            this.cropData.response = response;
            const file = Object.assign({}, this.cropData);
            let index = this.fileList.findIndex((item) => item.uid === file.uid);
            if (index > -1) {
                this.fileList.splice(index, 1, file);
            } else {
                this.fileList.push(file);
            }
            this.handleUploadSuccess(response, file, this.fileList);
        },
        // 上传前校检格式和大小
        handleBeforeUpload (file) {
            if (this.multiple && this.value.length >= this.limit) {
                this.handleExceed();
                return false;
            }
            const isLt = file.size / 1024 / 1024 < this.fileSize;
            if (!isLt) {
                this.$message.error(`上传图片大小不能超过 ${this.fileSize} MB!`);
            }
            this.uploadType = file.type;
            this.uploading = isLt;
            this.$emit('beforeUpload');
            return isLt;
        },
        handleChange (file, fileList) {
            this.uploading = false;
            this.fileList = fileList;
        },
        // 文件个数超出
        handleExceed () {
            this.$message.error(`最多上传${this.limit}张图片`);
        },
        // 上传失败
        handleUploadError (err) {
            this.uploading = false;
            this.$message.error('上传失败, 请重试');
            this.$emit('error', err);
        },
        // 上传成功回调
        handleUploadSuccess (response, file) {
            let url = response;
            this.uploading = false;
            this.$message.success('上传成功');
            if (this.responseFn) {
                url = this.responseFn(response, file, this.uploadType);
            }
            if (this.multiple) {
                if (Array.isArray(this.value)) {
                    this.$emit('input', [...this.value, url]);
                } else {
                    this.$emit('input', [url]);
                }
            } else {
                if (!this.drag) {
                    this.$emit('input', url);
                } else {
                    this.$emit('input', '');
                }
            }
        },
        clear () {
            this.$refs.upload.clearFiles();
        },
        handleRemove (index) {
            // this.$refs.upload.clearFiles();
            if (this.multiple) {
                const data = [...this.computedValues];
                data.splice(index, 1);
                this.fileList.splice(index, 1);
                this.$emit('input', data || []);
            } else {
                this.$emit('input', null);
                this.$emit('remove', '');
            }
        }
    }
};
</script>

<style>
    .ele-upload-image {
        line-height: 1;
        position: relative;
    }
    .ele-upload-image .el-loading-spinner {
        line-height: 1;
    }
    .ele-upload-image .el-icon-plus {
        vertical-align: middle;
    }
    .ele-upload-image .el-upload--picture-card {
        width: auto;
        height: auto;
        background: none;
        line-height: inherit;
    }
</style>
